package edu.se.jai.lesson03guess1.controller;

import edu.se.jai.lesson03guess1.model.Result;
import edu.se.jai.lesson03guess1.model.entity.GameRoom;
import edu.se.jai.lesson03guess1.model.message.WebSocketMessage;
import edu.se.jai.lesson03guess1.service.GameService;
import edu.se.jai.lesson03guess1.service.MessageSend;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.stereotype.Controller;

import java.util.List;

/**
 * 房间管理WebSocket控制器
 * 
 * 负责处理所有WebSocket消息，包括：
 * - 玩家连接和房间管理
 * - 房间生命周期控制（创建、加入、离开、解散）
 * - 消息路由和广播
 * 
 * 消息路由规则：
 * - /app/* : 客户端发送消息到服务器（全局操作）
 * - /room/{roomId} : 客户端发送消息到服务器（房间内操作）
 * - /user/queue/response : 服务器发送点对点消息给客户端
 * - /room/{roomId} : 服务器发送房间广播消息
 * - /topic/roomUpdate : 服务器发送全局广播消息
 */
@Slf4j
@Controller
@RequiredArgsConstructor
public class GameController {

    private final GameService gameService;
    private final MessageSend messageSend;

    /**
     * 处理玩家连接请求
     * 
     * @param playerName 玩家名称
     * @param headerAccessor 消息头访问器，用于获取会话ID
     */
    @MessageMapping("/connect")
    public void handleConnect(@Payload String playerName, SimpMessageHeaderAccessor headerAccessor) {
        String sessionId = headerAccessor.getSessionId();
        log.info("玩家 {} 尝试连接，Session ID: {}", playerName, sessionId);

        // 注册玩家会话
        Result<String> result = gameService.registerPlayerSession(sessionId, playerName);
        
        if (result.isSuccess()) {
            // 连接成功，发送成功消息
            messageSend.notifyConnect(playerName, sessionId, true, "连接成功");
        } else {
            // 连接失败，发送错误消息
            messageSend.notifyConnect(playerName, sessionId, false, result.getErrorMessage());
        }
    }

    /**
     * 处理创建房间请求
     * 
     * @param headerAccessor 消息头访问器，用于获取会话ID
     */
    @MessageMapping("/create")
    public void handleCreateRoom(SimpMessageHeaderAccessor headerAccessor) {
        String sessionId = headerAccessor.getSessionId();
        log.info("收到创建房间请求: sessionId={}", sessionId);

        // 调用服务创建房间
        Result<GameRoom> createResult = gameService.createRoom(sessionId);

        if (createResult.isSuccess()) {
            GameRoom room = createResult.getData();
            // 发送创建成功消息给创建者
            messageSend.notifyCreate(room, sessionId);
            // 广播房间更新给所有玩家
            messageSend.notifyRoomUpdate(room);
        } else {
            log.error("创建房间失败: {}", createResult.getErrorMessage());
            messageSend.notifyErrorMessage(sessionId, createResult.getErrorMessage());
        }
    }

    /**
     * 处理加入房间请求
     * 
     * @param roomId 房间ID
     * @param headerAccessor 消息头访问器，用于获取会话ID
     */
    @MessageMapping("/join")
    public void handleJoinRoom(@Payload String roomId, SimpMessageHeaderAccessor headerAccessor) {
        String sessionId = headerAccessor.getSessionId();
        log.info("收到加入房间请求: roomId={}, sessionId={}", roomId, sessionId);

        // 调用服务加入房间
        Result<GameRoom> result = gameService.joinRoom(sessionId, roomId);

        if (result.isSuccess()) {
            GameRoom room = result.getData();
            // 发送加入成功消息给当前玩家
            messageSend.notifyJoin(room, sessionId);
            // 广播房间更新给所有玩家
            messageSend.notifyRoomUpdate(room);
        } else {
            log.error("加入房间失败: {}", result.getErrorMessage());
            messageSend.notifyErrorMessage(sessionId, result.getErrorMessage());
        }
    }


    /**
     * 处理房间内消息（解散房间、离开房间等）
     * 
     * @param message 房间消息
     * @param roomId 房间ID
     * @param headerAccessor 消息头访问器，用于获取会话ID
     */
    @MessageMapping("/room/{roomId}")
    public void handleRoomMessage(@Payload WebSocketMessage message,
                                 @DestinationVariable String roomId,
                                 SimpMessageHeaderAccessor headerAccessor) {
        String sessionId = headerAccessor.getSessionId();
        log.info("收到房间消息: type={}, roomId={}, sessionId={}", message.getType(), roomId, sessionId);
        
        switch (message.getType()) {
            case DISSOLVE:
                // 解散房间
                Result<GameRoom> dissolveResult = gameService.dissolveRoom(sessionId, roomId);
                if (dissolveResult.isSuccess()) {
                    GameRoom room = dissolveResult.getData();
                    messageSend.notifyRoomDissolved(room);
                } else {
                    log.error("解散房间失败: {}", dissolveResult.getErrorMessage());
                    messageSend.notifyErrorMessage(sessionId, dissolveResult.getErrorMessage());
                }
                break;
                
            case LEAVE:
                // 离开房间
                Result<GameRoom> leaveResult = gameService.leaveRoom(sessionId, roomId);
                if (leaveResult.isSuccess()) {
                    GameRoom room = leaveResult.getData();
                    // 先发送离开消息给房间内其他玩家
                    messageSend.notifyLeave(room, sessionId);
                    // 再发送房间更新消息
                    messageSend.notifyRoomUpdate(room);
                } else {
                    log.error("离开房间失败: {}", leaveResult.getErrorMessage());
                    messageSend.notifyErrorMessage(sessionId, leaveResult.getErrorMessage());
                }
                break;

                
            default:
                log.warn("未知的房间消息类型: {}", message.getType());
                messageSend.notifyErrorMessage(sessionId, "未知的消息类型: " + message.getType());
        }
    }


    /**
     * 处理获取所有房间列表请求
     * 
     * @param headerAccessor 消息头访问器，用于获取会话ID
     */
    @MessageMapping("/allRooms")
    public void handleGetAllRooms(SimpMessageHeaderAccessor headerAccessor) {
        String sessionId = headerAccessor.getSessionId();
        log.info("获取所有房间列表请求，会话ID: {}", sessionId);
        
        // 获取所有房间
        List<GameRoom> allRooms = gameService.getAllRooms();
        log.info("找到 {} 个房间", allRooms.size());

        // 发送房间列表给请求者
        messageSend.notifyAllRooms(allRooms, sessionId);
    }
}
